//日志输出格式化类设计
#ifndef _M_FORMAT_H__
#define _M_FORMAT_H__

#include"message.hpp"
#include<vector>
#include<assert.h>
#include<string>
#include<sstream>
#include<memory>

#include <iomanip>

namespace bitlog{
    class FormatItem{
        public:
        using ptr=shared_ptr<FormatItem>;
        virtual void format(ostream& os,LogMsg& msg){}
    };
    class NameFormatItem:public FormatItem{
        public:
        NameFormatItem(const string& str="") {}
        void format(ostream& os,LogMsg& msg) override{
            os<<msg._name;
        }
    };
    //支持可配置宽度
    class LevelFormatItem:public FormatItem{
        public:
        LevelFormatItem(const string& str = "") {}
        void format(ostream& os, LogMsg& msg) override {
            os <<std::right << std::setw(8) << Loglevel::toString(msg._level);
        }
        // private:
        //     int _width;
        // public:
        //     LevelFormatItem(const string& str = "") : _width(8) {
        //         // 可以从字符串参数中解析宽度，如"level{8}"
        //         if (!str.empty()) {
        //             // 简单的解析逻辑，根据你的实际需求调整
        //             try {
        //                 _width = std::stoi(str);
        //             } catch (...) {
        //                 _width = 8; // 默认宽度
        //             }
        //         }
        //     }
            
        //     void format(ostream& os, LogMsg& msg) override {
        //         os << std::left << std::setw(_width) << Loglevel::toString(msg._level);
        //     }        

        // public:
        // LevelFormatItem(const string& str="") {}
        // void format(ostream& os,LogMsg& msg) override{
        //     os<<Loglevel::toString(msg._level);
        // }
    };
    class TidFormatItem:public FormatItem{
        public:
        TidFormatItem(const string& str="") {}
        void format(ostream& os,LogMsg& msg) override{
            os<<msg._tid;
        }
    };
    class FilenameFormatItem:public FormatItem{
        public:
        FilenameFormatItem(const string& str="") {}
        void format(ostream& os,LogMsg& msg) override{
            os<<msg._filename;
        }
    };
    class LineFormatItem:public FormatItem{
        public:
        LineFormatItem(const string& str="") {}
        void format(ostream& os,LogMsg& msg) override{
            os<<msg._line;
        }
    };
    class CtimeFormatItem:public FormatItem{
        private:
        string _format;
        public:
        CtimeFormatItem(const string& format="%H:%M:%S"):_format(format){
            if(format.empty()) _format="%H:%M:%S";
        }
        void format(ostream& os,LogMsg& msg) override{
            //将一个时间戳（time_t）转换为格式化的本地时间字符串
            time_t t=msg._ctime;
            struct tm lt;
            localtime_r(&t,&lt);
            char tmp[128];
            strftime(tmp,127,_format.c_str(),&lt);
            os<<tmp;
        }
    };
    class PayloadFormatItem:public FormatItem{
        public:
        PayloadFormatItem(const string& str="") {}
        void format(ostream& os,LogMsg& msg) override{
            os<<msg._payload;
        }
    };
    class TabFormatItem:public FormatItem{
        public:
        TabFormatItem(const string& str=""){}
        void format(ostream& os,LogMsg& msg) override{
            os<<"\t";
        }
    };
    class NLineFormatItem:public FormatItem{
        public:
        NLineFormatItem(const string& str=""){}
        void format(ostream& os,LogMsg& msg) override{
            os<<"\n";
        }
    };
    class OtherFormatItem:public FormatItem{
        private:
        string _str;
        public:
        OtherFormatItem(const string& str):_str(str) {}
        void format(ostream& os,LogMsg& msg) override{
            os<<_str;
        }
    };

    //日志器名称:%c   日志等级:%p    线程id:%t    文件名:%f    行号:%l    日期:%d    消息主体:%m    缩进:%T    换行:%n
    class Formatter{
        private:
        string _pattern;
        vector<FormatItem::ptr> _items;
        public:
        using ptr=shared_ptr<Formatter>;
        // %d{%H:%M:%S}%T%t%T[%p]%T[%c]%T%f:%l%T%m%n\n
        // [%d{%H:%M:%S}][%t][%p][%c][%f:%l]%m%n
        Formatter(const string& pattern="%d{%H:%M:%S}%T%t%T[%p]%T[%c]%T%f:%l%T%m%n"){
            _pattern=pattern;
            assert(parsePattern());
        }
        string pattern() {return _pattern;}
        string format(LogMsg& msg){
            stringstream ss;
            for(auto it:_items){
                it->format(ss,msg);
            }
            return ss.str();
        }
        ostream& format(ostream& os,LogMsg& msg){
            for(auto it:_items){
                it->format(os,msg);
            }
            return os;
        }
        bool parsePattern(){
            vector<tuple<string,string,int>> arry;
            string key;
            string value;
            string row;
            bool sub_fmt_error;
            size_t pos=0;
            while(pos<_pattern.size()){
                //首先判断它是否为非格式字符
                if(_pattern[pos]!='%'){
                    row.append(1,_pattern[pos++]);
                    continue;
                }
                if(_pattern[pos]=='%'&&_pattern[pos+1]=='%'){
                    row.append(1,_pattern[pos]);
                    pos+=2;
                }
                if(row.empty()==false){
                    arry.push_back(make_tuple(row,"",0));
                    row.clear();
                }

                //当前字符是'%'
                pos+=1;
                if(pos<_pattern.size()&&isalpha(_pattern[pos])){
                    key=_pattern[pos++];
                }else{
                    cout<<"%后面字符不合规"<<endl;
                    return false;
                }
                //检查是否有子格式化串
                if(pos<_pattern.size()&&_pattern[pos]=='{'){
                    sub_fmt_error=true;
                    pos++;
                    while(pos<_pattern.size()){
                        if(_pattern[pos]=='}'){
                            sub_fmt_error=false;
                            pos++;
                            break;
                        }
                        value.append(_pattern[pos++],1);
                    }
                }
                arry.push_back(make_tuple(key,value,1));
                key.clear();
                value.clear();
            }
            if(sub_fmt_error==true){
                cout<<"{}格式错误"<<endl;
                return false;
            }
            if(row.empty()==false){
                arry.push_back(make_tuple(row,"",0));
            }
            if(key.empty()==false){
                arry.push_back(make_tuple(key,value,1));
            }

            for(auto& it:arry){
                if(get<2>(it)==0){
                    FormatItem::ptr fi(new OtherFormatItem(get<0>(it)));
                    _items.push_back(fi);
                }else{
                    FormatItem::ptr fi=createItem(get<0>(it),get<1>(it));
                    if(fi.get()==nullptr){
                        cout<<"没有对应的格式化字符"<<endl;
                        return false;
                    }
                    _items.push_back(fi);
                }
            }
            return true;
        }
        private:
        FormatItem::ptr createItem(const string& fc,const string& subfmt){
            if(fc=="c") return FormatItem::ptr(new NameFormatItem);
            if(fc=="p") return FormatItem::ptr(new LevelFormatItem);
            if(fc=="t") return FormatItem::ptr(new TidFormatItem);
            if(fc=="f") return FormatItem::ptr(new FilenameFormatItem);
            if(fc=="l") return FormatItem::ptr(new LineFormatItem);
            if(fc=="d") return FormatItem::ptr(new CtimeFormatItem);
            if(fc=="m") return FormatItem::ptr(new PayloadFormatItem);
            if(fc=="T") return FormatItem::ptr(new TabFormatItem);
            if(fc=="n") return FormatItem::ptr(new NLineFormatItem);
            return FormatItem::ptr();
        }
    };
}


#endif